#!/usr/bin/env node

const request = require('request');
const fs = require('fs-extra');
const path = require('path');
const _ = require('lodash');
const utils = require('./js/utils');

function getMediaType(extname) {
    if (['.png', '.jpg', '.gif'].indexOf(extname) !== -1) {
        return { type: 'image', el: 'img' };
    }
    if (['.mp3'].indexOf(extname) !== -1) {
        return { type: 'audio', el: 'audio autoplay controls' };
    }
    if (['.mp4'].indexOf(extname) !== -1) {
        return { type: 'video', el: 'video autoplay controls' };
    }
}
function createBase64(imageFile, distFile, keepname) {
    const extname = path.extname(imageFile);
    if (['.png', '.jpg', '.gif', '.mp3', '.mp4'].indexOf(extname) === -1) {
        return console.log(`文件格式只支持 png/jpg/gif/mp3/mp4`);
    }
    const { type, el } = getMediaType(extname);
    if (path.basename(imageFile).startsWith('*.')) {
        if (!distFile || !distFile.endsWith('.js')) {
            return console.log('读取批量文件的distFile必须是js文件');
        }
        const list = keepname ? {} : [];
        let files = fs.readdirSync(path.dirname(imageFile));
        files = files.filter(o => o.endsWith(extname));
        files = _.orderBy(files, o => parseInt(o) || o);
        console.log('文件包括：', files);
        files.forEach(function (file) {
            const base64 = `data:${type}/${extname.substr(1)};base64,${fs.readFileSync(path.join(path.dirname(imageFile), file)).toString('base64')}`;
            keepname ? (list[file.replace(extname, '')] = base64) : list.push(base64);
        });
        fs.ensureDirSync(path.dirname(distFile));
        fs.writeFileSync(distFile, `module.exports=${JSON.stringify(list, null, 2)}`.replace(/"/g, `'`));
        return console.log(`生成文件：${distFile}`);
    }
    let destExtname;
    if (distFile == 'html' || distFile == '.html') {
        const basename = path.basename(imageFile).replace(extname, '');
        const dirname = path.dirname(imageFile);
        distFile = path.join(dirname, basename + '.html');
        destExtname = '.html';
    } else if (distFile == 'js' || distFile == '.js') {
        const basename = path.basename(imageFile).replace(extname, '');
        const dirname = path.dirname(imageFile);
        distFile = path.join(dirname, basename + '.js');
        destExtname = '.js';
    } else {
        const destPath = path.dirname(distFile);
        destExtname = path.extname(distFile);
        if (destExtname !== '.html' && destExtname !== '.js') {
            return console.log(`目标文件格式只支持 html/js`);
        }
        fs.ensureDirSync(destPath);
    }
    const header = destExtname === '.html' ? `<${el} src=` : 'module.exports=';
    const tail = destExtname === '.html' ? ' />' : '';
    let base64Buf = `${header}'data:${type}/${extname.substr(1)};base64,${fs.readFileSync(imageFile).toString('base64')}'${tail}`;
    fs.writeFileSync(distFile, base64Buf);

    console.log(`生成文件：${distFile}`);
}
function streamToBuffer(stream, encoding) {
    return new Promise(resolve => {
        const buffers = [];
        stream.on('error', () => resolve(null));
        stream.on('data', (data) => buffers.push(data));
        stream.on('end', () => resolve(!encoding ? Buffer.concat(buffers) : Buffer.concat(buffers).toString(encoding)));
    });
}
async function replaceImageFileToBase64(htmlFile, distFile, nourl) {
    if (!fs.existsSync(htmlFile)) {
        return console.log(`文件: ${htmlFile} 不存在`);
    }
    const srcPath = path.dirname(htmlFile);
    const lines = fs.readFileSync(htmlFile, 'utf-8').split('\n');
    fs.writeFileSync(distFile, '');
    for (let line of lines) {
        if (/.*src=['"][^'"]*['"].*/.test(line)) {
            const filename = line.replace(/.*src=['"]([^'"]*)['"].*/, '$1').trim();
            if (!/^https?:\/\//.test(filename)) {
                const extname = path.extname(filename);
                if (['.png', '.jpg', '.gif', '.mp3', '.mp4'].indexOf(extname) !== -1) {
                    const { type } = getMediaType(extname);
                    const header = `src="data:${type}/${extname.substr(1)};base64,`;
                    const imageBuf = fs.readFileSync(path.resolve(srcPath, filename));
                    const base64 = `${header}${imageBuf.toString('base64')}"`;
                    line = line.replace(/src=['"]([^'"]*)['"]/, base64);
                }
            } else if (nourl !== 'nourl') {
                const extname = path.extname(filename) || '.jpg';
                const { type } = getMediaType(extname);
                const header = `src="data:${type}/${extname.substr(1)};base64,`;
                let base64 = await streamToBuffer(request(filename), 'base64');
                base64 = `${header}${base64}"`;
                line = line.replace(/src=['"]([^'"]*)['"]/, base64);
            }
        }
        fs.appendFileSync(distFile, line + '\n');
    }
    console.log(`已经将文件 ${htmlFile} 中的图片全部替换为base64到文件 ${distFile} 中`);
}
async function genImageFromBase64(destFile = 'dist') {
    utils.paste((content = '') => {
        content = content.replace(/.*("|')?data:(image|audio|video)\//, '').replace(/("|').*/, '');
        const list = content.split(';base64,');
        if (list.length !== 2) {
            return console.log('请复制base64');
        }
        const type = list[0];
        destFile = !/\.(png|jpg|jpeg|mp3|mp4)/.test(destFile) ? `${destFile}.${type}` : destFile;
        const buffer = Buffer.from(list[1], 'base64');
        fs.writeFileSync(destFile, buffer, 'base64');
    });
}
function main(p1, p2, p3) {
    if (p1 === '-h' || p1 === '--help') {
        console.log('1. 将该文件夹下的*.x');
        console.log('   xbase64 "*.xx" [xx/]dest.js [keepname]');
        console.log('2. 将图片转为base64文件，可以是文件夹，html文件或js文件，直接用html|js使用原来的文件名');
        console.log('   xbase64 src.xx [([xx/]dest.html|.js)|html|js]');
        console.log('3. 将html文件中的图片全部替换为base64');
        console.log('   xbase64 src.html dest.html [nourl]');
        console.log('4. 将clipboard中的base64生成图片|音频');
        console.log('   xbase64 base64 [[xx/]dest[.jpg|.png|.mp3|.mp4]]');
        console.log('   后缀名：.jpg|.png|.gif|.mp3|.mp4');
        return;
    }
    const extname = path.extname(p1);
    if (extname === '.html') {
        replaceImageFileToBase64(p1, p2, p3);
    } else {
        const extname = path.extname(p1);
        if (['.png', '.jpg', '.gif', '.mp3', '.mp4'].indexOf(extname) !== -1) {
            createBase64(p1, p2, p3);
        } else {
            if (p1 === 'base64') {
                genImageFromBase64(p2);
            }
        }
    }
}

main(...process.argv.slice(2));
